/**************************************************************************** 
* 
* Copyright (c) 2023  C*Core -   All Rights Reserved  
* 
* THIS SOFTWARE IS DISTRIBUTED "AS IS," AND ALL WARRANTIES ARE DISCLAIMED, 
* INCLUDING MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* 
* PROJECT     : CCFC2011BC           
* DESCRIPTION : CCFC2011BC pit low level drivers code 
* HISTORY     : Initial version
* @file     pit_lld.c
* @version  1.1
* @date     2023 - 02 - 20
* @brief    Initial version.
* 
*****************************************************************************/

#include "pit_lld.h"
#include "IntcInterrupts.h"
#include "lldconf.h"
#include "intc_lld.h"
#include "sys.h"
/*===========================================================================*/
/* Driver exported variables.                                                */
/*===========================================================================*/
PITDriver PITD;
/**
 * @brief   PIT driver identifier.
 */

/*===========================================================================*/
/* Driver local variables and types.                                         */
/*===========================================================================*/

/*===========================================================================*/
/* Driver local functions.                                                   */
/*===========================================================================*/
/*===========================================================================*/
/* Driver interrupt handlers.                                                */
/*===========================================================================*/
#if (PIT_CHANNEL_CH0_ENABLED == TRUE)
/**
 * @brief   PIT CHANNEL 0 interrupt handler.
 *
 * @isr
 */
static IRQ_HANDLER(PIT_CH0_HANDLER)
{
    IRQ_PROLOGUE();
    /* call the related callback */
    if (PITD.pit_ch_config[0].callback != NULL)
    {
        PITD.pit_ch_config[0].callback();
    }
    PITD.pit_tagp->CH[0].TFLG.R = 1;
    IRQ_EPILOGUE();
}
#endif
#if (PIT_CHANNEL_CH1_ENABLED == TRUE)
/**
 * @brief   PIT CHANNEL 1 interrupt handler.
 *
 * @isr
 */
static IRQ_HANDLER(PIT_CH1_HANDLER)
{
    IRQ_PROLOGUE();
    /* call the related callback */
    if (PITD.pit_ch_config[1].callback != NULL)
    {
        PITD.pit_ch_config[1].callback();
    }
    PITD.pit_tagp->CH[1].TFLG.R = 1;
    IRQ_EPILOGUE();
}
#endif

#if (PIT_CHANNEL_CH2_ENABLED == TRUE)
/**
 * @brief   PIT CHANNEL 2 interrupt handler.
 *
 * @isr
 */
static IRQ_HANDLER(PIT_CH2_HANDLER)
{
    IRQ_PROLOGUE();
    /* call the related callback */
    if (PITD.pit_ch_config[2].callback != NULL)
    {
        PITD.pit_ch_config[2].callback();
    }
    PITD.pit_tagp->CH[2].TFLG.R = 1;
    IRQ_EPILOGUE();
}
#endif

#if (PIT_CHANNEL_CH3_ENABLED == TRUE)
/**
 * @brief   PIT CHANNEL 3 interrupt handler.
 *
 * @isr
 */
static IRQ_HANDLER(PIT_CH3_HANDLER)
{
    IRQ_PROLOGUE();
    /* call the related callback */
    if (PITD.pit_ch_config[3].callback != NULL)
    {
        PITD.pit_ch_config[3].callback();
    }
    PITD.pit_tagp->CH[3].TFLG.R = 1;
    IRQ_EPILOGUE();
}
#endif

#if (PIT_CHANNEL_CH4_ENABLED == TRUE)
/**
 * @brief   PIT CHANNEL 4 interrupt handler.
 *
 * @isr
 */
static IRQ_HANDLER(PIT_CH4_HANDLER)
{
    IRQ_PROLOGUE();
    /* call the related callback */
    if (PITD.pit_ch_config[4].callback != NULL)
    {
        PITD.pit_ch_config[4].callback();
    }
    PITD.pit_tagp->CH[4].TFLG.R = 1;
    IRQ_EPILOGUE();
}
#endif

#if (PIT_CHANNEL_CH5_ENABLED == TRUE)
/**
 * @brief   PIT CHANNEL 5 interrupt handler.
 *
 * @isr
 */
static IRQ_HANDLER(PIT_CH5_HANDLER)
{
    IRQ_PROLOGUE();
    /* call the related callback */
    if (PITD.pit_ch_config[5].callback != NULL)
    {
            PITD.pit_ch_config[5].callback();
    }
    PITD.pit_tagp->CH[5].TFLG.R = 1;
    IRQ_EPILOGUE();
}
#endif

#if (PIT_CHANNEL_CH6_ENABLED == TRUE)
/**
 * @brief   PIT CHANNEL 6 interrupt handler.
 *
 * @isr
 */
static IRQ_HANDLER(PIT_CH6_HANDLER)
{
    IRQ_PROLOGUE();
    /* call the related callback */
    if (PITD.pit_ch_config[6].callback != NULL)
    {
        PITD.pit_ch_config[6].callback();
    }
    PITD.pit_tagp->CH[6].TFLG.R = 1;
    IRQ_EPILOGUE();
}
#endif

#if (PIT_CHANNEL_CH7_ENABLED == TRUE)
/**
 * @brief   PIT CHANNEL 7 interrupt handler.
 *
 * @isr
 */
static IRQ_HANDLER(PIT_CH7_HANDLER)
{
    IRQ_PROLOGUE();
    /* call the related callback */
    if (PITD.pit_ch_config[7].callback != NULL)
    {
        PITD.pit_ch_config[7].callback();
    }
    PITD.pit_tagp->CH[7].TFLG.R = 1;
    IRQ_EPILOGUE();
}
#endif



/*===========================================================================*/
/* Driver exported functions.                                                */
/*===========================================================================*/
/*******************************************************************************
 * @brief      Low level pit driver initialization.
 * @param[in]  pitd      pointer to the PITDriver object
 *             config    pointer to the config
 * @param[out] None
 * @retval     None
 * @notapi 
 *******************************************************************************/
void PIT_LLD_Init(PITDriver *pitd, PIT_CH_Config *config)
{
    /* Set pointer to the PITDriver object */
    PITD.pit_tagp = &PIT;
    /* Install interrupt handler for PIT*/
#if (PIT_CHANNEL_CH0_ENABLED == TRUE)
    INTC_InstallINTCInterruptHandler(PIT_CH0_HANDLER, PIT_CH0_INT_NUMBER, PIT_CH0_IRQ_PRIO);
#endif
#if (PIT_CHANNEL_CH1_ENABLED == TRUE)
    INTC_InstallINTCInterruptHandler(PIT_CH1_HANDLER, PIT_CH1_INT_NUMBER, PIT_CH1_IRQ_PRIO);
#endif
#if (PIT_CHANNEL_CH2_ENABLED == TRUE)
    INTC_InstallINTCInterruptHandler(PIT_CH2_HANDLER, PIT_CH2_INT_NUMBER, PIT_CH2_IRQ_PRIO);
#endif
#if (PIT_CHANNEL_CH3_ENABLED == TRUE)
    INTC_InstallINTCInterruptHandler(PIT_CH3_HANDLER, PIT_CH3_INT_NUMBER, PIT_CH3_IRQ_PRIO);
#endif
#if (PIT_CHANNEL_CH4_ENABLED == TRUE)
    INTC_InstallINTCInterruptHandler(PIT_CH4_HANDLER, PIT_CH4_INT_NUMBER, PIT_CH4_IRQ_PRIO);
#endif
#if (PIT_CHANNEL_CH5_ENABLED == TRUE)
    INTC_InstallINTCInterruptHandler(PIT_CH5_HANDLER, PIT_CH5_INT_NUMBER, PIT_CH5_IRQ_PRIO);
#endif
#if (PIT_CHANNEL_CH6_ENABLED == TRUE)
    INTC_InstallINTCInterruptHandler(PIT_CH6_HANDLER, PIT_CH6_INT_NUMBER, PIT_CH6_IRQ_PRIO);
#endif
#if (PIT_CHANNEL_CH7_ENABLED == TRUE)
    INTC_InstallINTCInterruptHandler(PIT_CH7_HANDLER, PIT_CH7_INT_NUMBER, PIT_CH7_IRQ_PRIO);
#endif
    /* set Driver configuration */
    pitd->pit_ch_config = config;
    /* Enable PIT */
    PIT_LLD_ModuleEnable();
}

/*******************************************************************************
 * @brief      Low level pit driver deinitialization.
 * @param[in]  pitd      pointer to the @p PITDriver object
 * @param[out] None
 * @retval     None
 * @notapi 
 *******************************************************************************/
void PIT_LLD_DeInit(PITDriver *pitd)
{
    uint8_t i = 0u;
    /* Clear configured structrue */
    pitd->pit_ch_config = NULL;
    for (i = 0u; i < 7u ; i++)
        {
            PIT_LLD_ChannelStop(i);
        }
    PIT_LLD_ModuleDisable();
}

/*******************************************************************************
 * @brief      start a PIT all Channel with frequency and callback defined in 
 *             the configurator
 * @param[in]  value        loadvalue
 *             pitd         pointer to the @p PITDriver object
 * @param[out] None
 * @retval     None
 * @notapi 
 *******************************************************************************/
void PIT_LLD_ConfiguredChannelStart(const PITDriver *pitd, uint32_t value)
{
    uint32_t i;
    for (i = 0u; i < 8u; i++)
    {
        /* Set configured loadvalue */
        pitd->pit_ch_config[i].loadValue = value;
        /* Set configured enabled */
        pitd->pit_ch_config[i].enabled = TRUE;
        if (pitd->pit_ch_config[i].enabled == TRUE)
        {
            /* Set load value*/
            pitd->pit_tagp->CH[i].LDVAL.R = pitd->pit_ch_config[i].loadValue;
            /* Clear interrupt flag */
            pitd->pit_tagp->CH[i].TFLG.R  = 1U;
            /* Timer active, interrupt enabled  */
            pitd->pit_tagp->CH[i].TCTRL.R = 3U;
        }
    }
}

/*******************************************************************************
 * @brief      Low level pit configured channel start.
 * @param[in]  channel      number of channel
 *             value        loadvalue
 *             pitd
 * @param[out] None
 * @retval     None
 * @notapi 
 *******************************************************************************/
void PIT_LLD_ChannelConf(const PITDriver *pitd, uint32_t channel, uint32_t value)
{
    /* Set configured enabled */
    pitd->pit_ch_config[channel].enabled = TRUE;
    /* Set configured loadvalue */
    pitd->pit_ch_config[channel].loadValue = value;
    if (pitd->pit_ch_config[channel].enabled == TRUE)
    {
        /* Set load value*/
        pitd->pit_tagp->CH[channel].LDVAL.R = pitd->pit_ch_config[channel].loadValue;
        /* Interrupt flag cleared */
        pitd->pit_tagp->CH[channel].TFLG.R  = 1U;
        /* Timer active, interrupt enabled. */
        pitd->pit_tagp->CH[channel].TCTRL.B.TIE = 1U;
        pitd->pit_tagp->CH[channel].TCTRL.B.TEN = 1U;
    }
}

/*******************************************************************************
 * @brief      Start a PIT Channel 
 * @param[in]  channel      number of channel
 * @param[out] None
 * @retval     None
 * @notapi 
 *******************************************************************************/
void PIT_LLD_ChannelStart(uint32_t channel)
{
    /* Set configured enabled */
    PITD.pit_ch_config[channel].enabled = TRUE;
    /* Timer Inactive */
    PIT.CH[channel].TCTRL.B.TEN = 1U;
}

/*******************************************************************************
 * @brief      Stop a PIT Channel 
 * @param[in]  channel      number of channel
 * @param[out] None
 * @retval     None
 * @notapi 
 *******************************************************************************/
void PIT_LLD_ChannelStop(uint32_t channel)
{
    /* Set configured enabled */
    PITD.pit_ch_config[channel].enabled = FALSE;
    /* Timer Inactive */
    PIT.CH[channel].TCTRL.B.TEN = 0U;
}

/*******************************************************************************
 * @brief      Enable or disable channel interrupt
 * @param[in]  channel      number of channel
 * @param[out] newState 1:enable    0:disable
 * @retval     None
 * @notapi 
 *******************************************************************************/
void PIT_LLD_SetChannelInterruptState(uint32_t channel, uint32_t newState)
{
    /*Enable or disable channel interrupt*/
    PIT.CH[channel].TCTRL.B.TIE = newState;
}

/*******************************************************************************
 * @brief      Get channel interrupt state
 * @param[in]  channel		number of channel
 * @param[out] 1:enable	0:disable
 * 
 * @retval     None
 * @notapi 
 *******************************************************************************/
uint32_t PIT_LLD_GetChannelInterruptState(uint32_t channel)
{
    /*Get channel interrupt state*/
    return PIT.CH[channel].TCTRL.B.TIE;
}

/*******************************************************************************
 * @brief      PIT_LLD_GetChannelState : Get PIT channel state
 * @param[in]  channel      number of channel
 * @param[out] 0:channel is stopped and interrupt is disable
 *             1:channel is started but interrupt is disable
 *             2:channel is stopped but interrupt is enable
 *             3:channel is started and interrupt is enable
 * @retval     None
 * @notapi
 *******************************************************************************/
uint32_t PIT_LLD_GetChannelState(uint32_t channel)
{
    /*Get channel interrupt and enable state*/
    return PIT.CH[channel].TCTRL.R;
}

/*******************************************************************************
 * @brief      PIT_LLD_ModuleDisable : STOP the PIT peripheral
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void PIT_LLD_ModuleDisable(void)
{
    /* PIT clock Disabled.*/
    PIT.PITMCR.B.MDIS = 1;
}

/*******************************************************************************
 * @brief      PIT_LLD_ModuleEnable : Enable the PIT module
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void PIT_LLD_ModuleEnable(void)
{
    PIT.PITMCR.B.MDIS = 0;
}


/*******************************************************************************
 * @brief      PIT_LLD_SetLoadValue : Set PIT load value
 * @param[in]  channel      number of channel
 *             loadValue    time start value
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void PIT_LLD_SetLoadValue(uint32_t channel, uint32_t loadValue)
{
    /* Set PIT loadvalue */
    PIT.CH[channel].LDVAL.B.TSV = loadValue;
}

/*******************************************************************************
 * @brief      PIT_LLD_GetLoadValue : Get PIT load value
 * @param[in]  channel      number of channel
 * @param[out] oadValue time of start value
 * @retval     None
 * @notapi
 *******************************************************************************/
uint32_t PIT_LLD_GetLoadValue(uint32_t channel)
{
    /* Get PIT loadvalue */
    return PIT.CH[channel].LDVAL.B.TSV;
}

/*******************************************************************************
 * @brief      PIT_LLD_GetCurrentValue : Get PIT current value
 * @param[in]  channel      number of channel
 * @param[out] time of current value
 * @retval     None
 * @notapi
 *******************************************************************************/
uint32_t PIT_LLD_GetCurrentValue(uint32_t channel)
{
    /* Get PIT current count value */
    return PIT.CH[channel].CVAL.B.TVL;
}

/*******************************************************************************
 * @brief      PIT_LLD_ClearInterruptFlag : Clear interrupt flag.
 * @param[in]  channel      number of channel
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void PIT_LLD_ClearInterruptFlag(uint32_t channel)
{
    /* Interrupt flag cleared. */
    PIT.CH[channel].TFLG.R = 1;
}


/*******************************************************************************
 * @brief      PIT_LLD_FreezeMode : Set Freeze mode.
 * @param[in]  state    state of freeze mode
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void PIT_LLD_FreezeMode(uint32_t state)
{
    /* Set PIT Freeze mode */
    PIT.PITMCR.B.FRZ = state;
}

